﻿/**********************************************************************************
Program:       chinaweathergadget

License:       GNU/GPL version 3

File:          NewComboBox.cs

Description:   重写的 ComboBox 类

Author:        Guangyu Liu （lgy0417@gmail.com）

Environment:   .NET Framework v2.0 or later version

Usage/Example: README_chs.txt

Last Modified: 2010.08.04

***********************************************************************************/


using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.ComponentModel;
using System.Drawing.Imaging;


namespace PrettifiedControls
{
	namespace PrettifiedComboBox
	{
		public class ComboBoxNew : ComboBox
		{
			#region Fields

			private IntPtr _editHandle;
			private ControlState _buttonState;
			private Color _baseColor = Color.FromArgb(51, 161, 224);
			private Color _borderColor = Color.FromArgb(51, 161, 224);
			private Color _arrowColor = Color.FromArgb(19, 88, 128);
			private bool _bPainting;

			#endregion

			#region Constructors

			public ComboBoxNew() : base()
			{
				SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			}

			#endregion

			#region Properties

			public Color BaseColor
			{
				get { return _baseColor; }
				set 
				{
					if (_baseColor != value)
					{
						_baseColor = value;
						base.Invalidate();
					}
				}
			}

			public Color BorderColor
			{
				get { return _borderColor; }
				set
				{
					if (_borderColor != value)
					{
						_borderColor = value;
						base.Invalidate();
					}
				}
			}

			public Color ArrowColor
			{
				get { return _arrowColor; }
				set
				{
					if (_arrowColor != value)
					{
						_arrowColor = value;
						base.Invalidate();
					}
				}
			}

			internal ControlState ButtonState
			{
				get { return _buttonState; }
				set
				{
					if (_buttonState != value)
					{
						_buttonState = value;
						Invalidate(ButtonRect);
					}
				}
			}

			internal Rectangle ButtonRect
			{
				get
				{
					return GetDropDownButtonRect();
				}
			}

			internal bool ButtonPressed
			{
				get
				{
					if (IsHandleCreated)
					{
						return GetComboBoxButtonPressed();
					}
					return false;
				}
			}

			internal IntPtr EditHandle
			{
				get { return _editHandle; }
			}

			internal Rectangle EditRect
			{
				get
				{
					if (DropDownStyle == ComboBoxStyle.DropDownList)
					{
						Rectangle rect = new Rectangle(
							3, 3, Width - ButtonRect.Width - 6, Height - 6);
						if (RightToLeft == RightToLeft.Yes)
						{
							rect.X += ButtonRect.Right;
						}
						return rect;
					}
					if (IsHandleCreated && EditHandle != IntPtr.Zero)
					{
						NativeMethods.RECT rcClient = new NativeMethods.RECT();
						NativeMethods.GetWindowRect(EditHandle, ref rcClient);
						return RectangleToClient(rcClient.Rect);
					}
					return Rectangle.Empty;
				}
			}

			#endregion

			#region Override Methods

			protected override void OnCreateControl()
			{
				base.OnCreateControl();

				NativeMethods.ComboBoxInfo cbi = GetComboBoxInfo();
				_editHandle = cbi.hwndEdit;
			}

			protected override void OnMouseMove(MouseEventArgs e)
			{
				base.OnMouseMove(e);
				Point point = e.Location;
				if (ButtonRect.Contains(point))
				{
					ButtonState = ControlState.Hover;
				}
				else
				{
					ButtonState = ControlState.Normal;
				}
			}

			protected override void OnMouseEnter(EventArgs e)
			{
				base.OnMouseEnter(e);

				Point point = PointToClient(Cursor.Position);
				if (ButtonRect.Contains(point))
				{
					ButtonState = ControlState.Hover;
				}
			}

			protected override void OnMouseLeave(EventArgs e)
			{
				base.OnMouseLeave(e);

				ButtonState = ControlState.Normal;
			}

			protected override void OnMouseUp(MouseEventArgs e)
			{
				base.OnMouseUp(e);
				ButtonState = ControlState.Normal;
			}

			protected override void WndProc(ref Message m)
			{
				switch (m.Msg)
				{
					case NativeMethods.WM_PAINT:
						WmPaint(ref m);
						break;
					default:
						base.WndProc(ref m);
						break;
				}
			}

			#endregion

			#region Windows Message Methods

			private void WmPaint(ref Message m)
			{
				if (base.DropDownStyle == ComboBoxStyle.Simple)
				{
					base.WndProc(ref m);
					return;
				}

				if (base.DropDownStyle == ComboBoxStyle.DropDown)
				{
					if (!_bPainting)
					{
						NativeMethods.PAINTSTRUCT ps = 
							new NativeMethods.PAINTSTRUCT();

						_bPainting = true;
						NativeMethods.BeginPaint(m.HWnd, ref ps);

						RenderComboBox(ref m);

						NativeMethods.EndPaint(m.HWnd, ref ps);
						_bPainting = false;
						m.Result = NativeMethods.TRUE;
					}
					else
					{
						base.WndProc(ref m);
					}
				}
				else
				{
					base.WndProc(ref m);
					RenderComboBox(ref m);
				}
			}

			#endregion

			#region Render Methods

			private void RenderComboBox(ref Message m)
			{
				Rectangle rect = new Rectangle(Point.Empty, Size);
				Rectangle buttonRect = ButtonRect;
				ControlState state = ButtonPressed ?
					ControlState.Pressed : ButtonState;
				using (Graphics g = Graphics.FromHwnd(m.HWnd))
				{
					RenderComboBoxBackground(g, rect, buttonRect);
					RenderConboBoxDropDownButton(g, ButtonRect, state);
					RenderConboBoxBorder(g, rect);
				}
			}

			private void RenderConboBoxBorder(
				Graphics g, Rectangle rect)
			{
				Color borderColor = base.Enabled ?
					_borderColor : SystemColors.ControlDarkDark;
				using (Pen pen = new Pen(borderColor))
				{
					rect.Width--;
					rect.Height--;
					g.DrawRectangle(pen, rect);
				}
			}

			private void RenderComboBoxBackground(
				Graphics g, 
				Rectangle rect, 
				Rectangle buttonRect)
			{
				Color backColor = base.Enabled ?
					base.BackColor : SystemColors.Control;
				using (SolidBrush brush = new SolidBrush(backColor))
				{
					buttonRect.Inflate(-1, -1);
					rect.Inflate(-1, -1);
					using (Region region = new Region(rect))
					{
						region.Exclude(buttonRect);
						region.Exclude(EditRect);
						g.FillRegion(brush, region);
					}
				}
			}

			private void RenderConboBoxDropDownButton(
				Graphics g, 
				Rectangle buttonRect, 
				ControlState state)
			{
				Color baseColor;
				Color backColor = Color.FromArgb(160, 250, 250, 250);
				Color borderColor = base.Enabled ?
					_borderColor : SystemColors.ControlDarkDark;
				Color arrowColor = base.Enabled ? 
					_arrowColor : SystemColors.ControlDarkDark;
				Rectangle rect = buttonRect;

				if (base.Enabled)
				{
					switch (state)
					{
						case ControlState.Hover:
							baseColor = RenderHelper.GetColor(
								_baseColor, 0, -33, -22, -13);
							break;
						case ControlState.Pressed:
							baseColor = RenderHelper.GetColor(
								_baseColor, 0, -65, -47, -25);
							break;
						default:
							baseColor = _baseColor;
							break;
					}
				}
				else
				{
					baseColor = SystemColors.ControlDark;
				}

				rect.Inflate(-1, -1);

				RenderScrollBarArrowInternal(
					g,
					rect,
					baseColor,
					borderColor,
					backColor,
					arrowColor,
					RoundStyle.None,
					true,
					false,
					ArrowDirection.Down,
					LinearGradientMode.Vertical);
			}

			internal void RenderScrollBarArrowInternal(
			   Graphics g,
			   Rectangle rect,
			   Color baseColor,
			   Color borderColor,
			   Color innerBorderColor,
			   Color arrowColor,
			   RoundStyle roundStyle,
			   bool drawBorder,
			   bool drawGlass,
			   ArrowDirection arrowDirection,
			   LinearGradientMode mode)
			{
				RenderHelper.RenderBackgroundInternal(
				   g,
				   rect,
				   baseColor,
				   borderColor,
				   innerBorderColor,
				   roundStyle,
				   0,
				   .45F,
				   drawBorder,
				   drawGlass,
				   mode);

				using (SolidBrush brush = new SolidBrush(arrowColor))
				{
					RenderArrowInternal(
						g,
						rect,
						arrowDirection,
						brush);
				}
			}

			internal void RenderArrowInternal(
				Graphics g,
				Rectangle dropDownRect,
				ArrowDirection direction,
				Brush brush)
			{
				Point point = new Point(
					dropDownRect.Left + (dropDownRect.Width / 2),
					dropDownRect.Top + (dropDownRect.Height / 2));
				Point[] points = null;
				switch (direction)
				{
					case ArrowDirection.Left:
						points = new Point[] { 
							new Point(point.X + 2, point.Y - 3), 
							new Point(point.X + 2, point.Y + 3), 
							new Point(point.X - 1, point.Y) };
						break;

					case ArrowDirection.Up:
						points = new Point[] { 
							new Point(point.X - 3, point.Y + 2), 
							new Point(point.X + 3, point.Y + 2), 
							new Point(point.X, point.Y - 2) };
						break;

					case ArrowDirection.Right:
						points = new Point[] {
							new Point(point.X - 2, point.Y - 3), 
							new Point(point.X - 2, point.Y + 3), 
							new Point(point.X + 1, point.Y) };
						break;

					default:
						points = new Point[] {
							new Point(point.X - 2, point.Y - 1), 
							new Point(point.X + 3, point.Y - 1), 
							new Point(point.X, point.Y + 2) };
						break;
				}
				g.FillPolygon(brush, points);
			}

			#endregion

			#region Help Methods

			private NativeMethods.ComboBoxInfo GetComboBoxInfo()
			{
				NativeMethods.ComboBoxInfo cbi = new NativeMethods.ComboBoxInfo();
				cbi.cbSize = Marshal.SizeOf(cbi);
				NativeMethods.GetComboBoxInfo(base.Handle, ref cbi);
				return cbi;
			}

			private bool GetComboBoxButtonPressed()
			{
				NativeMethods.ComboBoxInfo cbi = GetComboBoxInfo();
				return cbi.stateButton == 
					NativeMethods.ComboBoxButtonState.STATE_SYSTEM_PRESSED;
			}

			private Rectangle GetDropDownButtonRect()
			{
				NativeMethods.ComboBoxInfo cbi = GetComboBoxInfo();

				return cbi.rcButton.Rect;
			}

			#endregion
		}
		
		
		public enum ControlState
		{
			/// <summary>
			///  正常。
			/// </summary>
			Normal,
			/// <summary>
			/// 鼠标进入。
			/// </summary>
			Hover,
			/// <summary>
			/// 鼠标按下。
			/// </summary>
			Pressed,
			/// <summary>
			/// 获得焦点。
			/// </summary>
			Focused,
		}
		
		
		public enum RoundStyle
		{
			/// <summary>
			/// 四个角都不是圆角。
			/// </summary>
			None = 0,
			/// <summary>
			/// 四个角都为圆角。
			/// </summary>
			All = 1,
			/// <summary>
			/// 左边两个角为圆角。
			/// </summary>
			Left = 2,
			/// <summary>
			/// 右边两个角为圆角。
			/// </summary>
			Right = 3,
			/// <summary>
			/// 上边两个角为圆角。
			/// </summary>
			Top = 4,
			/// <summary>
			/// 下边两个角为圆角。
			/// </summary>
			Bottom = 5,
			/// <summary>
			/// 左下角为圆角。
			/// </summary>
			BottomLeft = 6,
			/// <summary>
			/// 右下角为圆角。
			/// </summary>
			BottomRight = 7,
		}
		
		
		internal class NativeMethods
		{
			#region Const

			public static readonly IntPtr FALSE = IntPtr.Zero;
			public static readonly IntPtr TRUE = new IntPtr(1);

			public const int WM_PAINT = 0x000F;

			#endregion

			#region ComboBoxButtonState

			public enum ComboBoxButtonState
			{
				STATE_SYSTEM_NONE = 0,
				STATE_SYSTEM_INVISIBLE = 0x00008000,
				STATE_SYSTEM_PRESSED = 0x00000008
			}

			#endregion

			#region RECT

			public struct RECT
			{
				public int Left;
				public int Top;
				public int Right;
				public int Bottom;

				public RECT(int left, int top, int right, int bottom)
				{
					Left = left;
					Top = top;
					Right = right;
					Bottom = bottom;
				}

				public RECT(Rectangle rect)
				{
					Left = rect.Left;
					Top = rect.Top;
					Right = rect.Right;
					Bottom = rect.Bottom;
				}

				public Rectangle Rect
				{
					get
					{
						return new Rectangle(
							Left,
							Top,
							Right - Left,
							Bottom - Top);
					}
				}

				public Size Size
				{
					get
					{
						return new Size(Right - Left, Bottom - Top);
					}
				}

				public static RECT FromXYWH(int x, int y, int width, int height)
				{
					return new RECT(x,
									y,
									x + width,
									y + height);
				}

				public static RECT FromRectangle(Rectangle rect)
				{
					return new RECT(rect.Left,
									 rect.Top,
									 rect.Right,
									 rect.Bottom);
				}
			}

			#endregion

			#region PAINTSTRUCT

			public struct PAINTSTRUCT
			{
				public IntPtr hdc;
				public int fErase;
				public RECT rcPaint;
				public int fRestore;
				public int fIncUpdate;
				public int Reserved1;
				public int Reserved2;
				public int Reserved3;
				public int Reserved4;
				public int Reserved5;
				public int Reserved6;
				public int Reserved7;
				public int Reserved8;
			}

			#endregion

			#region ComboBoxInfo Struct

			public struct ComboBoxInfo
			{
				public int cbSize;
				public RECT rcItem;
				public RECT rcButton;
				public ComboBoxButtonState stateButton;
				public IntPtr hwndCombo;
				public IntPtr hwndEdit;
				public IntPtr hwndList;
			}

			#endregion

			#region API Methods

			[DllImport("user32.dll")]
			public static extern bool GetComboBoxInfo(
				IntPtr hwndCombo, ref ComboBoxInfo info);

			[DllImport("user32.dll")]
			public static extern int GetWindowRect(IntPtr hwnd, ref RECT lpRect);

			[DllImport("user32.dll")]
			public static extern IntPtr BeginPaint(IntPtr hWnd, ref PAINTSTRUCT ps);

			[DllImport("user32.dll")]
			public static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT ps);

			#endregion
		}
		
		
		public sealed class ControlPaintEx
		{
			public static void DrawCheckedFlag(Graphics graphics, Rectangle rect, Color color)
			{
				PointF[] points = new PointF[3];
				points[0] = new PointF(
					rect.X + rect.Width / 4.5f,
					rect.Y + rect.Height / 2.5f);
				points[1] = new PointF(
					rect.X + rect.Width / 2.5f,
					rect.Bottom - rect.Height / 3f);
				points[2] = new PointF(
					rect.Right - rect.Width / 4.0f,
					rect.Y + rect.Height / 4.5f);
				using (Pen pen = new Pen(color, 2F))
				{
					graphics.DrawLines(pen, points);
				}
			}

			public static void DrawGlass(
				Graphics g, RectangleF glassRect, int alphaCenter, int alphaSurround)
			{
				DrawGlass(g, glassRect, Color.White, alphaCenter, alphaSurround);
			}

			public static void DrawGlass(
			   Graphics g,
				RectangleF glassRect,
				Color glassColor,
				int alphaCenter,
				int alphaSurround)
			{
				using (GraphicsPath path = new GraphicsPath())
				{
					path.AddEllipse(glassRect);
					using (PathGradientBrush brush = new PathGradientBrush(path))
					{
						brush.CenterColor = Color.FromArgb(alphaCenter, glassColor);
						brush.SurroundColors = new Color[] { 
							Color.FromArgb(alphaSurround, glassColor) };
						brush.CenterPoint = new PointF(
							glassRect.X + glassRect.Width / 2,
							glassRect.Y + glassRect.Height / 2);
						g.FillPath(brush, path);
					}
				}
			}

			public static void DrawBackgroundImage(
				Graphics g,
				Image backgroundImage,
				Color backColor,
				ImageLayout backgroundImageLayout,
				Rectangle bounds,
				Rectangle clipRect)
			{
				DrawBackgroundImage(
					g,
					backgroundImage,
					backColor,
					backgroundImageLayout,
					bounds,
					clipRect,
					Point.Empty,
					RightToLeft.No);
			}

			public static void DrawBackgroundImage(
				Graphics g,
				Image backgroundImage,
				Color backColor,
				ImageLayout backgroundImageLayout,
				Rectangle bounds,
				Rectangle clipRect,
				Point scrollOffset)
			{
				DrawBackgroundImage(
					g,
					backgroundImage,
					backColor,
					backgroundImageLayout,
					bounds,
					clipRect,
					scrollOffset,
					RightToLeft.No);
			}

			public static void DrawBackgroundImage(
				Graphics g,
				Image backgroundImage,
				Color backColor,
				ImageLayout backgroundImageLayout,
				Rectangle bounds,
				Rectangle clipRect,
				Point scrollOffset,
				RightToLeft rightToLeft)
			{
				if (g == null)
				{
					throw new ArgumentNullException("g");
				}
				if (backgroundImageLayout == ImageLayout.Tile)
				{
					using (TextureBrush brush = new TextureBrush(backgroundImage, WrapMode.Tile))
					{
						if (scrollOffset != Point.Empty)
						{
							Matrix transform = brush.Transform;
							transform.Translate((float)scrollOffset.X, (float)scrollOffset.Y);
							brush.Transform = transform;
						}
						g.FillRectangle(brush, clipRect);
						return;
					}
				}
				Rectangle rect = CalculateBackgroundImageRectangle(
					bounds,
					backgroundImage,
					backgroundImageLayout);
				if ((rightToLeft == RightToLeft.Yes) &&
					(backgroundImageLayout == ImageLayout.None))
				{
					rect.X += clipRect.Width - rect.Width;
				}
				using (SolidBrush brush2 = new SolidBrush(backColor))
				{
					g.FillRectangle(brush2, clipRect);
				}
				if (!clipRect.Contains(rect))
				{
					if ((backgroundImageLayout == ImageLayout.Stretch) ||
						(backgroundImageLayout == ImageLayout.Zoom))
					{
						rect.Intersect(clipRect);
						g.DrawImage(backgroundImage, rect);
					}
					else if (backgroundImageLayout == ImageLayout.None)
					{
						rect.Offset(clipRect.Location);
						Rectangle destRect = rect;
						destRect.Intersect(clipRect);
						Rectangle rectangle3 = new Rectangle(Point.Empty, destRect.Size);
						g.DrawImage(
							backgroundImage,
							destRect,
							rectangle3.X,
							rectangle3.Y,
							rectangle3.Width,
							rectangle3.Height,
							GraphicsUnit.Pixel);
					}
					else
					{
						Rectangle rectangle4 = rect;
						rectangle4.Intersect(clipRect);
						Rectangle rectangle5 = new Rectangle(
							new Point(rectangle4.X - rect.X, rectangle4.Y - rect.Y),
							rectangle4.Size);
						g.DrawImage(
							backgroundImage,
							rectangle4,
							rectangle5.X,
							rectangle5.Y,
							rectangle5.Width,
							rectangle5.Height,
							GraphicsUnit.Pixel);
					}
				}
				else
				{
					ImageAttributes imageAttr = new ImageAttributes();
					imageAttr.SetWrapMode(WrapMode.TileFlipXY);
					g.DrawImage(
						backgroundImage,
						rect,
						0,
						0,
						backgroundImage.Width,
						backgroundImage.Height,
						GraphicsUnit.Pixel,
						imageAttr);
					imageAttr.Dispose();
				}
			}

			internal static Rectangle CalculateBackgroundImageRectangle(
				Rectangle bounds,
				Image backgroundImage,
				ImageLayout imageLayout)
			{
				Rectangle rectangle = bounds;
				if (backgroundImage != null)
				{
					switch (imageLayout)
					{
						case ImageLayout.None:
							rectangle.Size = backgroundImage.Size;
							return rectangle;

						case ImageLayout.Tile:
							return rectangle;

						case ImageLayout.Center:
							{
								rectangle.Size = backgroundImage.Size;
								Size size = bounds.Size;
								if (size.Width > rectangle.Width)
								{
									rectangle.X = (size.Width - rectangle.Width) / 2;
								}
								if (size.Height > rectangle.Height)
								{
									rectangle.Y = (size.Height - rectangle.Height) / 2;
								}
								return rectangle;
							}
						case ImageLayout.Stretch:
							rectangle.Size = bounds.Size;
							return rectangle;

						case ImageLayout.Zoom:
							{
								Size size2 = backgroundImage.Size;
								float num = ((float)bounds.Width) / ((float)size2.Width);
								float num2 = ((float)bounds.Height) / ((float)size2.Height);
								if (num >= num2)
								{
									rectangle.Height = bounds.Height;
									rectangle.Width = (int)((size2.Width * num2) + 0.5);
									if (bounds.X >= 0)
									{
										rectangle.X = (bounds.Width - rectangle.Width) / 2;
									}
									return rectangle;
								}
								rectangle.Width = bounds.Width;
								rectangle.Height = (int)((size2.Height * num) + 0.5);
								if (bounds.Y >= 0)
								{
									rectangle.Y = (bounds.Height - rectangle.Height) / 2;
								}
								return rectangle;
							}
					}
				}
				return rectangle;
			}
		}
		
		
		public static class GraphicsPathHelper
		{
			/// <summary>
			/// 建立带有圆角样式的路径。
			/// </summary>
			/// <param name="rect">用来建立路径的矩形。</param>
			/// <param name="_radius">圆角的大小。</param>
			/// <param name="style">圆角的样式。</param>
			/// <param name="correction">是否把矩形长宽减 1,以便画出边框。</param>
			/// <returns>建立的路径。</returns>
			public static GraphicsPath CreatePath(
				Rectangle rect, int radius, RoundStyle style, bool correction)
			{
				GraphicsPath path = new GraphicsPath();
				int radiusCorrection = correction ? 1 : 0;
				switch (style)
				{
					case RoundStyle.None:
						path.AddRectangle(rect);
						break;
					case RoundStyle.All:
						path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
						path.AddArc(
							rect.Right - radius - radiusCorrection,
							rect.Y,
							radius,
							radius,
							270,
							90);
						path.AddArc(
							rect.Right - radius - radiusCorrection,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius, 0, 90);
						path.AddArc(
							rect.X,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius,
							90,
							90);
						break;
					case RoundStyle.Left:
						path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
						path.AddLine(
							rect.Right - radiusCorrection, rect.Y,
							rect.Right - radiusCorrection, rect.Bottom - radiusCorrection);
						path.AddArc(
							rect.X,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius,
							90,
							90);
						break;
					case RoundStyle.Right:
						path.AddArc(
							rect.Right - radius - radiusCorrection,
							rect.Y,
							radius,
							radius,
							270,
							90);
						path.AddArc(
						   rect.Right - radius - radiusCorrection,
						   rect.Bottom - radius - radiusCorrection,
						   radius,
						   radius,
						   0,
						   90);
						path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
						break;
					case RoundStyle.Top:
						path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
						path.AddArc(
							rect.Right - radius - radiusCorrection,
							rect.Y,
							radius,
							radius,
							270,
							90);
						path.AddLine(
							rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
							rect.X, rect.Bottom - radiusCorrection);
						break;
					case RoundStyle.Bottom:
						path.AddArc(
							rect.Right - radius - radiusCorrection,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius,
							0,
							90);
						path.AddArc(
							rect.X,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius,
							90,
							90);
						path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
						break;
					case RoundStyle.BottomLeft:
						path.AddArc(
							rect.X,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius,
							90,
							90);
						path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
						path.AddLine(
							rect.Right - radiusCorrection, 
							rect.Y, 
							rect.Right - radiusCorrection, 
							rect.Bottom - radiusCorrection);
						break;
					case RoundStyle.BottomRight:
						path.AddArc(
							rect.Right - radius - radiusCorrection,
							rect.Bottom - radius - radiusCorrection,
							radius,
							radius,
							0,
							90);
						path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
						path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
						break;
				}
				path.CloseFigure();

				return path;
			}
		}
		
		internal class RenderHelper
		{
			internal static void RenderBackgroundInternal(
				Graphics g,
				Rectangle rect,
				Color baseColor,
				Color borderColor,
				Color innerBorderColor,
				RoundStyle style,
				bool drawBorder,
				bool drawGlass,
				LinearGradientMode mode)
			{
				RenderBackgroundInternal(
					g,
					rect,
					baseColor,
					borderColor,
					innerBorderColor,
					style,
					8,
					drawBorder,
					drawGlass,
					mode);
			}

			internal static void RenderBackgroundInternal(
			   Graphics g,
			   Rectangle rect,
			   Color baseColor,
			   Color borderColor,
			   Color innerBorderColor,
			   RoundStyle style,
			   int roundWidth,
			   bool drawBorder,
			   bool drawGlass,
			   LinearGradientMode mode)
			{
				RenderBackgroundInternal(
					 g,
					 rect,
					 baseColor,
					 borderColor,
					 innerBorderColor,
					 style,
					 8,
					 0.45f,
					 drawBorder,
					 drawGlass,
					 mode);
			}

			internal static void RenderBackgroundInternal(
			   Graphics g,
			   Rectangle rect,
			   Color baseColor,
			   Color borderColor,
			   Color innerBorderColor,
			   RoundStyle style,
			   int roundWidth,
			   float basePosition,
			   bool drawBorder,
			   bool drawGlass,
			   LinearGradientMode mode)
			{
				if (drawBorder)
				{
					rect.Width--;
					rect.Height--;
				}

				using (LinearGradientBrush brush = new LinearGradientBrush(
					rect, Color.Transparent, Color.Transparent, mode))
				{
					Color[] colors = new Color[4];
					colors[0] = GetColor(baseColor, 0, 35, 24, 9);
					colors[1] = GetColor(baseColor, 0, 13, 8, 3);
					colors[2] = baseColor;
					colors[3] = GetColor(baseColor, 0, 35, 24, 9);

					ColorBlend blend = new ColorBlend();
					blend.Positions = new float[] { 0.0f, basePosition, basePosition + 0.05f, 1.0f };
					blend.Colors = colors;
					brush.InterpolationColors = blend;
					if (style != RoundStyle.None)
					{
						using (GraphicsPath path =
							GraphicsPathHelper.CreatePath(rect, roundWidth, style, false))
						{
							g.FillPath(brush, path);
						}

						if (baseColor.A > 80)
						{
							Rectangle rectTop = rect;

							if (mode == LinearGradientMode.Vertical)
							{
								rectTop.Height = (int)(rectTop.Height * basePosition);
							}
							else
							{
								rectTop.Width = (int)(rect.Width * basePosition);
							}
							using (GraphicsPath pathTop = GraphicsPathHelper.CreatePath(
								rectTop, roundWidth, RoundStyle.Top, false))
							{
								using (SolidBrush brushAlpha =
									new SolidBrush(Color.FromArgb(128, 255, 255, 255)))
								{
									g.FillPath(brushAlpha, pathTop);
								}
							}
						}

						if (drawGlass)
						{
							RectangleF glassRect = rect;
							if (mode == LinearGradientMode.Vertical)
							{
								glassRect.Y = rect.Y + rect.Height * basePosition;
								glassRect.Height = (rect.Height - rect.Height * basePosition) * 2;
							}
							else
							{
								glassRect.X = rect.X + rect.Width * basePosition;
								glassRect.Width = (rect.Width - rect.Width * basePosition) * 2;
							}
							ControlPaintEx.DrawGlass(g, glassRect, 170, 0);
						}

						if (drawBorder)
						{
							using (GraphicsPath path =
								GraphicsPathHelper.CreatePath(rect, roundWidth, style, false))
							{
								using (Pen pen = new Pen(borderColor))
								{
									g.DrawPath(pen, path);
								}
							}

							rect.Inflate(-1, -1);
							using (GraphicsPath path =
								GraphicsPathHelper.CreatePath(rect, roundWidth, style, false))
							{
								using (Pen pen = new Pen(innerBorderColor))
								{
									g.DrawPath(pen, path);
								}
							}
						}
					}
					else
					{
						g.FillRectangle(brush, rect);
						if (baseColor.A > 80)
						{
							Rectangle rectTop = rect;
							if (mode == LinearGradientMode.Vertical)
							{
								rectTop.Height = (int)(rectTop.Height * basePosition);
							}
							else
							{
								rectTop.Width = (int)(rect.Width * basePosition);
							}
							using (SolidBrush brushAlpha =
								new SolidBrush(Color.FromArgb(128, 255, 255, 255)))
							{
								g.FillRectangle(brushAlpha, rectTop);
							}
						}

						if (drawGlass)
						{
							RectangleF glassRect = rect;
							if (mode == LinearGradientMode.Vertical)
							{
								glassRect.Y = rect.Y + rect.Height * basePosition;
								glassRect.Height = (rect.Height - rect.Height * basePosition) * 2;
							}
							else
							{
								glassRect.X = rect.X + rect.Width * basePosition;
								glassRect.Width = (rect.Width - rect.Width * basePosition) * 2;
							}
							ControlPaintEx.DrawGlass(g, glassRect, 200, 0);
						}

						if (drawBorder)
						{
							using (Pen pen = new Pen(borderColor))
							{
								g.DrawRectangle(pen, rect);
							}

							rect.Inflate(-1, -1);
							using (Pen pen = new Pen(innerBorderColor))
							{
								g.DrawRectangle(pen, rect);
							}
						}
					}
				}
			}

			internal static Color GetColor(Color colorBase, int a, int r, int g, int b)
			{
				int a0 = colorBase.A;
				int r0 = colorBase.R;
				int g0 = colorBase.G;
				int b0 = colorBase.B;

				if (a + a0 > 255) { a = 255; } else { a = Math.Max(0, a + a0); }
				if (r + r0 > 255) { r = 255; } else { r = Math.Max(0, r + r0); }
				if (g + g0 > 255) { g = 255; } else { g = Math.Max(0, g + g0); }
				if (b + b0 > 255) { b = 255; } else { b = Math.Max(0, b + b0); }

				return Color.FromArgb(a, r, g, b);
			}
		}
	}
}




/* 原始版权信息予以保留：
 * 作者：Starts_2000
 * 日期：2009-09-20
 * 网站：http://www.csharpwin.com CS 程序员之窗。
 * 你可以免费使用或修改以下代码，但请保留版权信息。
 * 具体请查看 CS程序员之窗开源协议（http://www.csharpwin.com/csol.html）。
 */
